package littlecyberwar.ui;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;

import littlecyberwar.ModelChangedListener;
import littlecyberwar.model.*;
import littlecyberwar.tool.*;
import littlecyberwar.ui.*;
import littlecyberwar.util.*;

import ModuleBuilder.model.*;


/**
 * Title:        LittleCyberWar
 * Description:  A online PBEM or PBC (play be Chat) Miniature utility
 * Copyright:    Copyright (c) 2001
 * Company:      S&S Enterprise
 * @author Milton Soong
 * @version 1.0
 */

public class PlayingBoardPanel extends JPanel
  implements MouseListener, MouseMotionListener, ModelChangedListener {

	public static final int _DEFAULT_STROKE_WIDTH=3;
	private static PlayingBoardPanel instance;

  private PlayingBoardModel model;
  private InternalCmdFacade cmdFacade;
  private ChatPanel chatOutPanel;
  private AffineTransform identTrans;
  Point startPoint;
  MouseStraightForwardHandler straightH;
  MouseHandler currHandler;
  Image mapImage;
  Stroke outlineStroke;
  public static final int _STROKE_WIDTH=2;
  private JLabel sideViewLabel;
  private JPanel chatPanel;
  private JLabel statusLabel;
  MapDrawerDelegate mapDrawer;
  
	//*** DEBUG
	static AffineTransform at = AffineTransform.getScaleInstance(0.5, 0.5);
	

  
  public PlayingBoardPanel() {
	// setBackground(Color.green);
	setDoubleBuffered(true);
	addMouseListener(this);
	addMouseMotionListener(this);
	identTrans = new AffineTransform();
	this.setAutoscrolls(true);
	outlineStroke = new BasicStroke(_DEFAULT_STROKE_WIDTH, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, _STROKE_WIDTH);
	mapDrawer = new MapDrawerDelegate();
	instance = this;
  }
  
  public static PlayingBoardPanel getInstance() {
  	return ( instance );
  }
  
  public void setModel(PlayingBoardModel m) {
    model = m;
    model.subscribeModelChange(this);
    cmdFacade = new InternalCmdFacade( (ModelChangeFacade)Util.lookup.get(Util._MODEL_FACADE) );
  }

	public InternalCmdFacade getInternalCmdFacade(){
		return (cmdFacade);
	}
	
  public void setChatOutput( ChatPanel l ) {
    chatOutPanel = l;
  }
  
  public void setStatusOutput( JLabel l ) {	
	statusLabel = l;
  }
  
  public void setChatPanel( JPanel chat ) {
  	chatPanel = chat;
  }

  public void setSideViewLabel( JLabel sideViewIn ) {
    sideViewLabel = sideViewIn;
  }

  /**
   * for another component to access the sideView lable
   * (mainly for the mouse handlers to set image to the lable when a new
   * vector is selected).
   */
  public JLabel getSideViewLabel () {
    return ( sideViewLabel );
  }

  public void mousePressed(MouseEvent e) {
    // saySomething("Mouse pressed; # of clicks: " + e.getClickCount(), e);
// see which element is selected (if any)
// the boolean anythingSelected is no longer used for anything
    boolean anythingSelected = currHandler.checkSelection(e);
  }

  public void mouseReleased(MouseEvent e) {
	UnitCommand cmd = currHandler.mouseUp(e);
	if ( cmd != null ) {
		cmdFacade.addCmd(cmd, null);
	}		
  }

  public void mouseEntered(MouseEvent e) {
     // saySomething("Mouse entered", e);
  }

  public void mouseExited(MouseEvent e) {
     // saySomething("Mouse exited", e);
  }

  public void mouseClicked(MouseEvent e) {
     //saySomething("Mouse clicked (# of clicks: "+ e.getClickCount() + ")", e);
 	currHandler.mouseClicked(e);
  }

  public void saySomething(String s, MouseEvent e ) {
    String more = new String(" " + e.getX() + "," + e.getY());
    statusLabel.setText(s+more);
  }

  public void printToStatus(String s) {
    // statusLabel.addOutput(s);
    statusLabel.setText( s );
  }

  public void mouseDragged(MouseEvent e) {
	// scroll to visible for every case where draging might cause the viewport to go off screen
	Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
	// ((JPanel)e.getSource()).scrollRectToVisible(r);
	this.scrollRectToVisible(r);
	// !! For now just drag the selected rectangle outline
	//
    currHandler.mouseDragged(e);
  }

  public void mouseMoved(MouseEvent e) {
  }

  public void paintComponent( Graphics g ) {
    // for now just paint a stupid rectangle
	super.paintComponent(g);
	Graphics2D g2 = (Graphics2D)g;
	g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
	
	ScalingDelegate.adjustScale(g2); 
	
	// first paint the background map
	//
	mapDrawer.drawMap(g2);
	paintUnits(g2);
	// draw the outline of the selected rectangle
	//
	currHandler.paintStuff(g2);
  }

/**
 * @param g2
 */
public void paintUnits(Graphics2D g2) {
	LayeredUnitHandler.paintUnits(g2);
	return;
}


  /**
   * first preserve the current selected unit shape that's used
   * in previous tool and set it in new tool
   */
  public void setMouseHandler( MouseHandler h ) {
	if ( h instanceof MultiSelectMouseHandler ) {
		// debug
		ArrayList al = ((MultiSelectMouseHandler)h).getSelectedElements();
		// Debug.out("currNum of selected elements = " + al.size() );
		
		if ( !(currHandler instanceof MultiSelectMouseHandler) ){
			setMultiMouseToSingleMouseHandler(h);
		}
	} else {
		if ( currHandler instanceof MultiSelectMouseHandler ){
			setSingleMouseToMultiMouseHandler(h);
		}
	}

	Shape s = null;
	if ( currHandler != null ) {
		s = currHandler.getSelectedRectangle();
	}
	currHandler = h;
	
	currHandler.setSelectedRectangle(s);
	currHandler.setModelFacade(cmdFacade);
	currHandler.handlerSelected();

	// debug
	if ( currHandler instanceof MultiSelectMouseHandler ) {
		ArrayList al = ((MultiSelectMouseHandler)currHandler).getSelectedElements();
		//Debug.out("after new handler assignment: currNum of selected elements = " + al.size() );
	}
	
	/**
	 * Print out the noUnitSelected Text from the handler if nothing selected
	 * Else printout selected text
	 */
	s = currHandler.getSelectedRectangle();
	if ( s == null ) {
		// no unit selected
	   currHandler.setNoUnitSelectedHelpText();
	} else {
	   currHandler.setUnitSelectedHelpText();
	}

	return;
  }

private void setMultiMouseToSingleMouseHandler( MouseHandler h ){
	if ( currHandler != null ) {
		currHandler.resetSelectedElements();
	}
	return;
}

private void setSingleMouseToMultiMouseHandler( MouseHandler h ){
}


private void setSingleMouseToSingleMouseHandler( MouseHandler h ) {
	Shape s = null;
	if ( currHandler != null ) {
		s = currHandler.getSelectedRectangle();
	}
	currHandler = h;
	currHandler.setSelectedRectangle(s);
	currHandler.setModelFacade(cmdFacade);
	
	/**
	 * Print out the noUnitSelected Text from the handler if nothing selected
	 * Else printout selected text
	 */
	s = currHandler.getSelectedRectangle();
	if ( s == null ) {
		// no unit selected
	   currHandler.setNoUnitSelectedHelpText();
	} else {
	   currHandler.setUnitSelectedHelpText();
	}
	return;
}
	/**
	 * This is called by the ScenarioManager delegate to load an array of images into the map
	 * @param img
	 */
  public void setMapImage( ImageElement[][] allImg, int colIn, int rowIn) {
  	mapDrawer.setMapImage(allImg, colIn, rowIn, true);
	Dimension d = mapDrawer.getMapSize();
	mapSizeChanged(d);
  	return;
  }
  
  public void mapSizeChanged(Dimension d) {
	this.setPreferredSize(d);
	this.revalidate();
	repaint();
	return;
  }
  
  public Dimension getMapSize() {
  	return ( mapDrawer.getMapSize());
  }
  
  public void modelChanged(Rectangle r) {
  	repaint(r);
  }

  public void modelChanged() {
    repaint();
  }
/**
 * @return
 */
public MouseHandler getCurrHandler() {
	return currHandler;
}

}